﻿using System;
using System.Diagnostics;
using System.Threading;
using System.Collections.Generic;
using System.Windows.Forms;

//自定义命名空间
using DreamCube.Foundation.DllImport;
using DreamCube.Foundation.Basic.Utility;
using RemotingFramework = DreamCube.Framework.Utilities.Remoting;

namespace BGN.PlugIn.Client
{
    public static class IEWinHelper
    {
        private static List<Object[]> commands = new List<Object[]>();
        static Process currentIEProcess = null;

        /// <summary>
        /// 内部标识状态的枚举类型
        /// </summary>
        private enum Status
        {
            /// <summary>
            /// 标识正在打开
            /// </summary>
            isOpenning = 0,

            /// <summary>
            /// 已经打开了
            /// </summary>
            hasOpened = 1,

            /// <summary>
            /// 关闭状态
            /// </summary>
            hasClosed = 2
        }

        /// <summary>
        /// 当前的状态是关闭状态
        /// </summary>
        private static Int32 CurrentSinfoStatus = (Int32)Status.hasClosed;

        private static BGN.Common.Remoting.SystemCommand sysCommand = null;

        /// <summary>
        /// 当接收到客户端连接的事件
        /// </summary>
        public static void OnClientConnect()
        {
            if (CurrentSinfoStatus != (Int32)Status.hasOpened)
            {
                InitialRemotingClient();
                CurrentSinfoStatus = (Int32)Status.hasOpened; //如果收到IE发过来的Remoting消息，则证明已经正常打开了sinfo系统
            }
        }

        /// <summary>
        /// 然后初始化remoting客户端
        /// </summary>
        private static void InitialRemotingClient()
        {
            try
            {
                RemotingFramework.Client.Instance.InitialClient(); //初始化remoting
                String sPort = CommonConfiger.Instance.GetBGNToActiveXRemotingPort();
                Int32 iPort = -1;
                Int32.TryParse(sPort, out iPort);
                sysCommand = RemotingFramework.Server.Instance.CreateRemotingObj<BGN.Common.Remoting.SystemCommand>(iPort, "tcp", "127.0.0.1", false);
            }
            catch (Exception ex)
            {
                MyLog.MakeLog(ex);
            }
        }

        private static List<Int32> commandList = new List<Int32>();

        /// <summary>
        /// 发送命令到OA系统
        /// </summary>
        /// <param name="userLoginName">布谷鸟系统的用户名</param>
        /// <param name="userName">布谷鸟系统的用户姓名</param>
        /// <param name="userPassword"></param>
        /// <param name="command"></param>
        /// <param name="args"></param>
        public static void SendCommandToOASystem(String userLoginName, String userName, String userPassword, String command, String[] args)
        {
            OpenOASystem(userLoginName, userName, userPassword);
            String argValueStr = "";
            if (args != null) argValueStr = MyEnumerable.JoinEx(args, ";");

            Object[] values = new Object[2];
            values[0] = command;
            values[1] = args;

            ThreadPool.QueueUserWorkItem(DoExecSInfoCommand, values);
        }

        private static DateTime lastClickTime = new DateTime(2012, 1, 1); //初始化的时候设置一个很早的值

        /// <summary>
        /// 登陆SInfo系统
        /// </summary>
        /// <param name="userLoginName">登陆布谷鸟系统的【用户名】，是用户名，不是姓名</param>
        /// <param name="userName">登陆布谷鸟系统的【姓名】，不是用户名</param>
        /// <param name="userPassword">登陆布谷鸟系统的用户密码</param>
        /// <param name="browserPath">可以指定浏览器的Exe路径</param>
        public static void OpenOASystem(String userLoginName, String userName, String userPassword, String browserPath = "")
        {
            String url = CommonConfiger.Instance.GetXmlConfigNodeInnerText("IndexUrl");
            if (String.IsNullOrEmpty(url))
            {
                MessageBox.Show("无法登录Sinfo系统，没有找到Sinfo的登陆网址配置信息！");
                return;
            }
            //当一登陆布谷鸟系统，马上点击进入OA系统的时候，this._UserName属性还没获取到值
            if (String.IsNullOrEmpty(userLoginName)) return;

            if ((DateTime.Now - lastClickTime).TotalSeconds < 5) //单击太频繁了，必须间隔大于10s
            {
                CurrentSinfoStatus = (Int32)IEWinHelper.Status.hasOpened;
                return;
            }

            lastClickTime = DateTime.Now;

            //判断是否已经打开了sinfo系统
            if (Myshdocvw.IsBrowserOpenUrl(url, Myshdocvw.UrlMatchType.StartWith))
                return;
            //如果当前是关闭状态，则调用打开方法，打开sinfo系统，并标识状态为：isOpenning
            //用于过滤单次很多次的情况
            CurrentSinfoStatus = (Int32)Status.isOpenning;
            try
            {
                Model.User user = null;
                SinfoUserHelper.UserStated checkResult = SinfoUserHelper.CheckUser(userLoginName, userPassword, out user);
                if (checkResult == SinfoUserHelper.UserStated.NotExistUserName)
                {
                    MessageBox.Show(String.Format("SInfo系统不存在用户【{0}】，请联系管理员添加该用户！", userLoginName), "提醒", MessageBoxButtons.OK);
                    return;
                }
                else if (checkResult == SinfoUserHelper.UserStated.PasswordNotRight)
                {
                    MessageBox.Show(String.Format("【{0}】，您好！您在布谷鸟系统的登陆密码与SInfo系统的登陆密码不一致，要从布谷鸟系统登录SInfo系统，必须先把布谷鸟系统的密码同步到SInfo系统中！", userName), "提醒", MessageBoxButtons.OK);
                    UpdateSinfoPassword updatePWForm = new UpdateSinfoPassword(user, userPassword);
                    if (updatePWForm.ShowDialog() == DialogResult.OK)
                        OpenSinfoWithIE(url, CommonConfiger.Instance.GetSystemID(), userLoginName, userPassword);
                }
                else if (checkResult == SinfoUserHelper.UserStated.Match)
                {
                    //直接打开OA系统
                    OpenSinfoWithIE(url, CommonConfiger.Instance.GetSystemID(), userLoginName, userPassword, browserPath);
                }
            }
            catch (Exception)
            {
                CurrentSinfoStatus = (Int32)IEWinHelper.Status.hasClosed; //当发生异常的时候，应该重置状态
                throw;
            }
        }

        #region "私有方法"

        /// <summary>
        /// 执行Sinfo命令的方法
        /// </summary>
        /// <param name="values"></param>
        private static void DoExecSInfoCommand(Object values)
        {
            Object[] paramArray = values as Object[];
            if (paramArray != null && paramArray.Length == 2)
            {
                //长时间等待客户端IE打开，打开后就发送命令过去
                Int32 i = 0;
                while (IEWinHelper.CurrentSinfoStatus != (Int32)IEWinHelper.Status.hasOpened)
                {
                    if (i >= 50) break;  //退出循环
                    i++;
                    System.Threading.Thread.Sleep(2000);
                }
                //如果是在OA系统没有打开的情况下，第一次发送命令的话，则需要先等待一下再发送命令，等待OA系统登录完毕先
                if (i > 0) System.Threading.Thread.Sleep(2000);
                //如果打开了浏览器，则执行命令
                if (IEWinHelper.CurrentSinfoStatus == (Int32)IEWinHelper.Status.hasOpened)
                    ExecSinfoCommand(paramArray[0].ToString(), (String[])paramArray[1]);
            }
        }

        /// <summary>
        /// 执行sinfo的命令
        /// </summary>
        private static void ExecSinfoCommand(String command,String [] args)
        {
            try
            {
                if (sysCommand != null)
                {
                    sysCommand.SendSystemCommandToClient(command);
                }
                else
                {
                    CurrentSinfoStatus = (Int32)Status.hasClosed;
                }
            }
            catch (Exception ex)
            {
                CurrentSinfoStatus = (Int32)Status.hasClosed;
                MyLog.MakeLog(ex);
            }
        }

        private static Object locker = new Object();
        /// <summary>
        /// 清除sinfo的命令
        /// </summary>
        private static void ClearSinfoCommand()
        {
            if (commands.Count == 0) return;
            lock (locker)
            {
                if (commands.Count == 0) return;
                for (Int32 i = 0; i < commands.Count; i++)
                {
                    ExecSinfoCommand(commands[i][0].ToString(), commands[i][1] as String[]);
                    System.Threading.Thread.Sleep(1000);
                }
                commands.Clear();
            }
        }

        private static System.Threading.Timer timer = null;  //预防定时器被回收了

        /// <summary>
        /// 采用IE打开sinfo系统
        /// </summary>
        /// <param name="sinfoUrl"></param>
        /// <param name="systemID"></param>
        /// <param name="user"></param>
        private static void OpenSinfoWithIE(String sinfoUrl, String systemID, String userName, String userPassword, String browserPath = "")
        {
            //判断是否有配置浏览器程序的路径
            if (String.IsNullOrEmpty(browserPath))
            {
                currentIEProcess = System.Diagnostics.Process.Start(
                                                    String.Format("{0}OACommon/OASmart/login.aspx?{1}",
                                                                    sinfoUrl.EndsWith("/") ? sinfoUrl : sinfoUrl + "/",
                                                                    BasicObjects.MyEncrypt.Encrypt(String.Format("username={0}&password={1}&SystemID={2}&type=bgn", userName, userPassword, systemID))));
            }
            else
            {
                currentIEProcess = System.Diagnostics.Process.Start(browserPath,
                                                                  String.Format("{0}OACommon/OASmart/login.aspx?{1}",
                                                                                  sinfoUrl.EndsWith("/") ? sinfoUrl : sinfoUrl + "/",
                                                                                  BasicObjects.MyEncrypt.Encrypt(String.Format("username={0}&password={1}&SystemID={2}&type=bgn", userName, userPassword, systemID))));
            }
        }

        static void currentIEProcess_Exited(object sender, EventArgs e)
        {
            CurrentSinfoStatus = (Int32)Status.hasClosed;
        }

        static void currentIEProcess_Disposed(object sender, EventArgs e)
        {
            CurrentSinfoStatus = (Int32)Status.hasClosed;
        }

        #endregion
    }
}
